﻿using System.Drawing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using Zero.UControl.Component.ScreenCut;
using Point = System.Windows.Point;
using Color = System.Windows.Media.Color;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
using ColorConverter = System.Windows.Media.ColorConverter;

namespace Zero.UControl.Demo.Views.ScreenCut
{
    /// <summary>
    /// ScreenCutView.xaml 的交互逻辑
    /// </summary>
    public partial class ScreenCutView : Window
    {
        private bool _isDragging;                   // 框选
        private bool _rectDragging;                 // 选框拖拽
        private bool _allowZoom;                    // 是否允许放大
        private bool _isDebug = false;              // 开启调试输出
        private static int screenWidth;             // 屏幕宽度
        private static int screenHeight;            // 屏幕高度
        private System.Drawing.Color pixelColor;    // 像素点rgba
        private BitmapSource bitmap;                // 截取区域的位图
        private BitmapSource screenBitmap;          // 全屏屏幕位图
        private ColorMode ColorMode = ColorMode.RGB;    // 颜色显示模式

        public event EventHandler<BitmapSource> OperateCompleted;

        private RectangleGeometry _clipGeometry = new();

        static ScreenCutView()
        {
            // 获取主屏幕的物理尺寸（不受 DPI 影响）
            screenWidth = GetSystemMetrics(SM_CXSCREEN);
            screenHeight = GetSystemMetrics(SM_CYSCREEN);
        }

        public ScreenCutView()
        {
            InitializeComponent();
            Loaded += ScreenCutView_Loaded;
            SelectionRectangle.MouseMove += Image_MouseMove;
            SelectionRectangle.MouseLeave += Image_MouseLeave;
        }

        #region 事件

        private void ScreenCutView_Loaded(object sender, RoutedEventArgs e)
        {
            screenBitmap = CreateFullScreenBitmap();
        }

        private async void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.F2)
            {
                await CropRegion();
                OperateCompleted?.Invoke(this, bitmap);
                //this.Close();
            }
            else if (e.Key == Key.F1 && Keyboard.Modifiers == ModifierKeys.Control)
            {
                OperateCompleted?.Invoke(this, screenBitmap);
            }
            else if (e.Key == Key.F3)
            {
                await CropRegion();
                ScreenShotWindow screenShotWindow = new ScreenShotWindow(bitmap);
                screenShotWindow.Left = Canvas.GetLeft(SelectionRectangle);
                screenShotWindow.Top = Canvas.GetTop(SelectionRectangle);
                screenShotWindow.Show();
            }
            else if (e.Key == Key.C)
            {
                string color = GetColor();
                Clipboard.SetText(color);
                this.Close();
            }
            else if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
            {
                ColorMode = ColorMode == ColorMode.RGB ? ColorMode.HEX : ColorMode.RGB;
                // Shift 按下立即变化
                ColorInfoText.Text = $"{GetColor()}";
                e.Handled = true; // 尽可能阻止系统响应，避免操作系统进行中英文切换
            }
            else if (e.Key == Key.Escape)
            {
                this.Close();
            }
        }
        #endregion

        #region 辅助方法
        private string GetColor()
        {
            string color = string.Empty;
            // 获取当前像素值
            byte r = pixelColor.R;
            byte g = pixelColor.G;
            byte b = pixelColor.B;
            switch (ColorMode)
            {
                case ColorMode.RGB:
                    // 保存到剪贴板
                    color = $"{r}, {g}, {b}";
                    break;
                case ColorMode.HEX:
                    color = $"#{r.ToString("X2")}{g.ToString("X2")}{b.ToString("X2")}";
                    break;
                default:
                    break;
            }
            return color;
        }
        #endregion

        #region win32接口

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetCursorPos(out POINT lpPoint);

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int X;
            public int Y;

            public POINT(int x, int y)
            {
                this.X = x;
                this.Y = y;
            }

            public POINT(double x, double y)
            {
                this.X = (int)x;
                this.Y = (int)y;
            }
        }


        [DllImport("user32.dll")]
        static extern int GetSystemMetrics(int nIndex);

        const int SM_CXSCREEN = 0; // 屏幕宽度
        const int SM_CYSCREEN = 1; // 屏幕高度

        #endregion

        #region 框选
        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            _isDragging = true;
            _allowZoom = false;

            Point point = e.GetPosition(cvs);
            SizePopup.HorizontalOffset = Canvas.GetLeft(cvs);
            SizePopup.VerticalOffset = Canvas.GetTop(cvs) - 34;
            SizePopup.Visibility = Visibility.Visible;
            SizePopup.IsOpen = true;

            SelectionRectangle.Visibility = Visibility.Visible;
            UpdateSelection(point, point);

            SelectionRectangle.SizeChanged -= SelectionRectangle_SizeChanged;
        }

        private void Window_MouseMove(object sender, MouseEventArgs e)
        {
            if (_isDragging)
            {
                _allowZoom = false;
                // 获取屏幕坐标
                double left = Canvas.GetLeft(SelectionRectangle);
                double top = Canvas.GetTop(SelectionRectangle);
                Point point1 = new Point(left, top);
                Point point2 = e.GetPosition(cvs);

                // 显示区域大小
                double w = SelectionRectangle.ActualWidth;
                double h = SelectionRectangle.ActualHeight;
                string posInfo = $"{w} X {h}";
                SizeText.Text = posInfo;

                // 更新选中区域
                UpdateSelection(point1, point2);
            }
        }

        private async void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            SelectionRectangle.ShowBorder = true;
            _isDragging = false;

            SelectionRectangle.SizeChanged += SelectionRectangle_SizeChanged;
        }
        #endregion

        #region 选中更新

        private const double MinDelta = 0.5; // 限流阈值，可根据实际情况调整
        private Point _lastUpdatePoint1;
        private Point _lastUpdatePoint2;

        private void UpdateSelection(Point p1, Point p2)
        {
            // 限流判断（保留逻辑）
            double dx1 = Math.Abs(p1.X - _lastUpdatePoint1.X);
            double dy1 = Math.Abs(p1.Y - _lastUpdatePoint1.Y);
            double dx2 = Math.Abs(p2.X - _lastUpdatePoint2.X);
            double dy2 = Math.Abs(p2.Y - _lastUpdatePoint2.Y);

            if (dx1 < MinDelta && dy1 < MinDelta && dx2 < MinDelta && dy2 < MinDelta)
                return;

            _lastUpdatePoint1 = p1;
            _lastUpdatePoint2 = p2;

            // 计算当前坐标
            double x = Math.Min(p1.X, p2.X);
            double y = Math.Min(p1.Y, p2.Y);
            double w = Math.Abs(p2.X - p1.X);
            double h = Math.Abs(p2.Y - p1.Y);

            Canvas.SetLeft(SelectionRectangle, x);
            Canvas.SetTop(SelectionRectangle, y);
            SelectionRectangle.Width = w;
            SelectionRectangle.Height = h;

            // 遮罩处理求差集运算（不变）
            var fullRect = new RectangleGeometry(new Rect(0, 0, screenWidth, screenHeight));
            var holeRect = new RectangleGeometry(new Rect(x, y, w, h));
            var combined = new CombinedGeometry(GeometryCombineMode.Exclude, fullRect, holeRect);

            // 遮罩区域（combined）透明度 128 -> 50%
            // 洞区域（holeRect）	没有被填充  0 -> 完全透明
            var geometryDrawing = new GeometryDrawing
            {
                Geometry = combined,
                Brush = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0))
            };

            var drawingBrush = new DrawingBrush(geometryDrawing)
            {
                Stretch = Stretch.None,
                AlignmentX = AlignmentX.Left,
                AlignmentY = AlignmentY.Top
            };

            MaskRectangle.OpacityMask = drawingBrush;
        }

        private void UpdateMoveRect(Point point)
        {
            Canvas.SetLeft(SelectionRectangle, point.X);
            Canvas.SetTop(SelectionRectangle, point.Y);

            // 遮罩处理求差集运算（不变）
            var fullRect = new RectangleGeometry(new Rect(0, 0, screenWidth, screenHeight));
            var holeRect = new RectangleGeometry(new Rect(point.X, point.Y, SelectionRectangle.ActualWidth, SelectionRectangle.ActualHeight));
            var combined = new CombinedGeometry(GeometryCombineMode.Exclude, fullRect, holeRect);

            var geometryDrawing = new GeometryDrawing
            {
                Geometry = combined,
                Brush = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0))
            };

            var drawingBrush = new DrawingBrush(geometryDrawing)
            {
                Stretch = Stretch.None,
                AlignmentX = AlignmentX.Left,
                AlignmentY = AlignmentY.Top
            };

            MaskRectangle.OpacityMask = drawingBrush;
        }
        #endregion

        #region 区域裁剪
        /// <summary>
        /// 像素坐标系转屏幕坐标系
        /// </summary>
        /// <returns></returns>
        public List<Point> Region2Screen()
        {
            // 计算截图区域（以屏幕物理像素为单位）
            int x = (int)(Canvas.GetLeft(SelectionRectangle) + 2);
            int y = (int)(Canvas.GetTop(SelectionRectangle) + 2);
            int width = (int)(SelectionRectangle.ActualWidth - 4);
            int height = (int)(SelectionRectangle.ActualHeight - 4);

            // 像素坐标系转屏幕坐标系
            Point ap1 = new Point(x, y);
            Point ap2 = new Point(x + width, y + height);
            Point sp1 = PointToScreen(ap1); 
            Point sp2 = PointToScreen(ap2);
            return new List<Point> { sp1, sp2 };
        }

        /// <summary>
        /// 根据框选区域创建位图
        /// </summary>
        /// <returns></returns>
        private BitmapSource CreateBitmap(List<Point> points = null)
        {
            if (screenBitmap == null)
                return null;

            if (points == null || points.Count == 0)
                points = Region2Screen();

            Point sp1 = points[0];
            Point sp2 = points[1];

            int x = (int)sp1.X;
            int y = (int)sp1.Y;
            int width = (int)(sp2.X - sp1.X);
            int height = (int)(sp2.Y - sp1.Y);

            if (width <= 0 || height <= 0)
                return null;

            // 从 screenBitmap 中裁剪
            //  注意：
            //      这里的 screenBitmap 最初就是通过CopyFromScreen从屏幕坐标系进行截取的，这里可以直接使用屏幕坐标系的位置进行截取
            return new CroppedBitmap(screenBitmap, new Int32Rect(x, y, width, height));
        }


        /// <summary>
        /// 创建全屏屏幕快照
        /// </summary>
        /// <returns></returns>
        public BitmapSource? CreateFullScreenBitmap()
        {
            using var bmp = new Bitmap(screenWidth, screenHeight, PixelFormat.Format32bppArgb);
            using var g = Graphics.FromImage(bmp);
            g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(screenWidth, screenHeight), CopyPixelOperation.SourceCopy);
            IntPtr intPtr = bmp.GetHbitmap();
            try
            {
                screenBitmap = Imaging.CreateBitmapSourceFromHBitmap(
                    intPtr,
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions()
                );
                Clipboard.SetImage(screenBitmap);
                return screenBitmap;
            }
            finally
            {
                Base.Helper.ImageHelper.DelObject(intPtr);
            }
        }

        /// <summary>
        /// 裁剪选中区域
        /// </summary>
        public async Task CropRegion()
        {
            try
            {
                List<Point> points = Region2Screen();
                bitmap = CreateBitmap(points);
                bitmap.Freeze();    // 避免跨线程 UI 访问异常
                // 拷贝到剪贴板
                if (bitmap != null)
                {
                    Clipboard.SetImage(bitmap);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("截图失败：" + ex.Message);
            }
        }

        #endregion

        #region 选框拖动 (DIP坐标系处理)

        Point oldPoint;
        private void SelectionRectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (_isDragging) return;
            _rectDragging = true;
            SelectionRectangle.Cursor = Cursors.SizeAll;

            oldPoint = e.GetPosition(cvs);
            SelectionRectangle.CaptureMouse();

            MagnifierPopup.IsOpen = false;
            e.Handled = true;
        }

        private void SelectionRectangle_MouseMove(object sender, MouseEventArgs e)
        {
            if (!_rectDragging) return;
            Point offsetPoint = e.GetPosition(cvs);
            int xdelta = (int)(offsetPoint.X - oldPoint.X);
            int ydelta = (int)(offsetPoint.Y - oldPoint.Y);

            // 变化量太小不进行重绘
            if (Math.Abs(xdelta) < MinDelta && Math.Abs(ydelta) < MinDelta)
                return;

            double left = Canvas.GetLeft(SelectionRectangle);
            double top = Canvas.GetTop(SelectionRectangle);
            double x = left + xdelta < 0 ? 0 : (left + xdelta + SelectionRectangle.ActualWidth > ActualWidth ? (ActualWidth - SelectionRectangle.ActualWidth) : left + xdelta);
            double y = top + ydelta < 0 ? 0 : (top + ydelta + SelectionRectangle.ActualHeight > ActualHeight ? (ActualHeight - SelectionRectangle.ActualHeight) : top + ydelta);
            Point startPoint = new Point(x, y);
            UpdateMoveRect(startPoint);

            oldPoint = offsetPoint;
        }

        private void SelectionRectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _rectDragging = false;
            SelectionRectangle.Cursor = Cursors.Arrow;
            SelectionRectangle.ReleaseMouseCapture();
        }

        #endregion

        #region 选框缩放

        private async void SelectionRectangle_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            double left = Canvas.GetLeft(SelectionRectangle);
            double top = Canvas.GetTop(SelectionRectangle);
            double right = left + SelectionRectangle.ActualWidth;
            double bottom = top + SelectionRectangle.ActualHeight;

            UpdateSelection(new Point(left, top), new Point(right, bottom));
        }

        #endregion

        #region 放大效果
        private void Image_MouseMove(object sender, MouseEventArgs e)
        {
            if (_isDragging || _rectDragging) return;

            Task.Run(async () =>
            {
                await Task.Delay(1000);
                this.Dispatcher.Invoke(() =>
                {
                    _allowZoom = true;
                });
            });

            if (!_allowZoom) return;

            // 获取鼠标相对于选框的位置
            GetCursorPos(out POINT point);
            List<Point> points = Region2Screen();

            // 边缘区域不生效
            int border = 5;
            // 判断当前点是否在选中区域
            if (point.X > (points[0].X + border) && point.Y > (points[0].Y + border) && point.X < (points[1].X - border) && point.Y < (points[1].Y - border))
            {
                int x = point.X;
                int y = point.Y;

                // 创建一个 1x1 的 bitmap 来获取这个像素的颜色
                using var bmp = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
                using var g = Graphics.FromImage(bmp);
                g.CopyFromScreen(x, y, 0, 0, new System.Drawing.Size(1, 1), CopyPixelOperation.SourceCopy);

                pixelColor = bmp.GetPixel(0, 0);
                PosInfoText.Text = $"({x},{y})";
                ColorBox.Fill = new SolidColorBrush(Color.FromRgb(pixelColor.R, pixelColor.G, pixelColor.B));
                ColorInfoText.Text = $"{GetColor()}";
                // 显示或处理像素值（你可以绑定 TextBlock 显示 RGB）
                Debug.WriteLineIf(_isDebug, $"像素位置: ({x},{y}), 颜色: R: {pixelColor.R},G: {pixelColor.G},B: {pixelColor.B}");

                double left = Canvas.GetLeft(SelectionRectangle);
                double top = Canvas.GetTop(SelectionRectangle);
                Point pPoint = e.GetPosition(cvs);

                // w,h => 21 map to 210 每一个像素放大10倍
                // 这里取出一个 21x21的区域，将这个区域放大到210x210的图像源中
                int size = 10;
                x = x - size;
                y = y - size;
                int w = x + size > screenWidth ? (screenWidth - x) : 2 * size + 1;
                int h = y + size > screenHeight ? (screenHeight - y) : 2 * size + 1;
                Debug.WriteLineIf(_isDebug, $"x: {x},y: {y},bitmap w: {w},h: {h}");
                CroppedBitmap cropped = new CroppedBitmap(screenBitmap, new Int32Rect(x, y, w, h));
                // 显示到 ZoomImage 中（自动拉伸填充）
                MagnifierImage.Source = cropped;

                // 设置Popup位置（相对屏幕）
                MagnifierPopup.HorizontalOffset = pPoint.X + 20;
                MagnifierPopup.VerticalOffset = pPoint.Y + 20;
                MagnifierPopup.Visibility = Visibility.Visible;
                MagnifierPopup.IsOpen = true;
                //Debug.WriteLine($"Image_MouseMove _isDragging : {_isDragging},_rectDragging: {_rectDragging}");
                SelectionRectangle.Cursor = Cursors.Cross;
            }
            else
            {
                MagnifierPopup.Visibility = Visibility.Hidden;
                MagnifierPopup.IsOpen = false;
                SelectionRectangle.Cursor = Cursors.Arrow;
            }
        }

        private void Image_MouseLeave(object sender, MouseEventArgs e)
        {
            MagnifierPopup.IsOpen = false;
        }
        #endregion
    }

    internal enum ColorMode
    {
        RGB,
        HEX
    }
}
